/*
 * Copyright (c) 2020-2099 the original author or authors. All rights reserve.
 */
package org.tianyun.cloud.security.configuration;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.tianyun.cloud.security.token.store.TokenStoreEnum;

import java.util.List;

/**
 * 安全配置类
 *
 * @auther ebert_chan
 */
public class SecurityProperties implements InitializingBean {

    /**
     * 是否启用
     */
    private boolean enabled;

    /**
     * token生成策略
     */
    private YamlTokenStrategy tokenStrategy;

    /**
     * api加解密配置
     */
    private YamlApiEncryptProperties apiEncrypt;

    // getter and setter

    public YamlTokenStrategy getTokenStrategy() {
        return tokenStrategy;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void setTokenStrategy(YamlTokenStrategy tokenStrategy) {
        this.tokenStrategy = tokenStrategy;
    }

    public YamlApiEncryptProperties getApiEncrypt() {
        return apiEncrypt;
    }

    public void setApiEncrypt(YamlApiEncryptProperties apiEncrypt) {
        this.apiEncrypt = apiEncrypt;
    }

    /*
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        if (getTokenStrategy() != null) {
            Assert.state(!(getTokenStrategy().getStandard() == null && getTokenStrategy().getJwt() == null), "Please set the token-strategy, standard or jwt.");
            Assert.state(!(getTokenStrategy().getStandard() != null && getTokenStrategy().getJwt() != null), "Set only one token-strategy.");

            if (getTokenStrategy().getStandard() != null) {
                Assert.notNull(getTokenStrategy().getStandard().getKey(), "standard token-strategy 'key' cannot be empty.");
                Assert.notNull(getTokenStrategy().getStandard().getIv(), "standard token-strategy 'iv' cannot be empty.");
            }

            if (getTokenStrategy().getJwt() != null) {
                Assert.notNull(getTokenStrategy().getJwt().getSecret(), "jwt token-strategy 'secret' cannot be empty.");
            }
        }

        if (getApiEncrypt() != null && getApiEncrypt().isEnabled()) {
            Assert.notNull(getApiEncrypt().getKey(), "api-encrypt 'key' cannot be empty.");
        }
    }

    // static classes

    public static class YamlApiEncryptProperties {

        /**
         * 是否启用加解密
         */
        private boolean enabled;

        /**
         * rsa加解密key
         */
        private String key;

        /**
         * 加解密白名单uri，不进行加解密操作
         */
        private List<String> whiteUri;

        // getter and setter

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public List<String> getWhiteUri() {
            return whiteUri;
        }

        public void setWhiteUri(List<String> whiteUri) {
            this.whiteUri = whiteUri;
        }

    }

    /**
     * token策略配置
     *
     * @auther ebert_chan
     */
    public static class YamlTokenStrategy {

        /**
         * token store enum, default MEMORY
         */
        private TokenStoreEnum tokenStore = TokenStoreEnum.MEMORY;

        /**
         * accessToken有效时长（单位秒）
         */
        private Integer accessTokenValiditySeconds;

        /**
         * standard策略
         */
        private YamlStandardTokenStrategy standard;

        /**
         * jwt策略
         */
        private YamlJwtTokenStrategy jwt;

        /**
         * token有效性验证白名单，不校验token是否有效
         */
        private List<String> whiteUrl;

        // getter and setter

        public Integer getAccessTokenValiditySeconds() {
            return accessTokenValiditySeconds;
        }

        public TokenStoreEnum getTokenStore() {
            return tokenStore;
        }

        public void setTokenStore(TokenStoreEnum tokenStore) {
            this.tokenStore = tokenStore;
        }

        public void setAccessTokenValiditySeconds(Integer accessTokenValiditySeconds) {
            this.accessTokenValiditySeconds = accessTokenValiditySeconds;
        }

        public YamlStandardTokenStrategy getStandard() {
            return standard;
        }

        public void setStandard(YamlStandardTokenStrategy standard) {
            this.standard = standard;
        }

        public YamlJwtTokenStrategy getJwt() {
            return jwt;
        }

        public void setJwt(YamlJwtTokenStrategy jwt) {
            this.jwt = jwt;
        }

        public List<String> getWhiteUrl() {
            return whiteUrl;
        }

        public void setWhiteUrl(List<String> whiteUrl) {
            this.whiteUrl = whiteUrl;
        }

    }

    /**
     * standard模式策略
     *
     * @auther ebert_chan
     */
    public static class YamlStandardTokenStrategy {

        /**
         * aes key
         */
        private String key;

        /**
         * aes iv
         */
        private String iv;

        // getter and setter

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getIv() {
            return iv;
        }

        public void setIv(String iv) {
            this.iv = iv;
        }

    }

    /**
     * jwt模式策略
     *
     * @auther ebert_chan
     */
    public static class YamlJwtTokenStrategy extends YamlStandardTokenStrategy {

        /**
         * row datas encrypty
         */
        private boolean encryptyData;

        /**
         * jwt secret
         */
        private String secret;

        // getter and setter

        public String getSecret() {
            return secret;
        }

        public boolean isEncryptyData() {
            return encryptyData;
        }

        public void setEncryptyData(boolean encryptyData) {
            this.encryptyData = encryptyData;
        }

        public void setSecret(String secret) {
            this.secret = secret;
        }

        public boolean isEnableEncrypty() {
            return isEncryptyData() && StringUtils.hasLength(getKey()) && StringUtils.hasLength(getIv());
        }

    }

}
